﻿using EasyXaf.EntityDesigner.BusinessObjects.Enums;
using EasyXaf.EntityDesigner.CodeTemplates.Extensions;
using System.Text;

namespace EasyXaf.EntityDesigner.CodeTemplates;

public class EnumTemplate : TemplateBase
{
    public Enumeration Enumeration { get; }

    public EnumTemplate(Enumeration enumeration)
    {
        Enumeration = enumeration;
    }

    private IEnumerable<string> Namespaces
    {
        get
        {
            var namespaces = new List<string>();

            if (!string.IsNullOrWhiteSpace(Enumeration.Caption) || !string.IsNullOrWhiteSpace(Enumeration.Description))
            {
                namespaces.Add("System.ComponentModel");
            }

            foreach (var enumValue in Enumeration.Values)
            {
                if (!string.IsNullOrWhiteSpace(enumValue.Caption))
                {
                    namespaces.Add("DevExpress.ExpressApp.DC");
                }

                if (!string.IsNullOrWhiteSpace(enumValue.Description))
                {
                    namespaces.Add("System.ComponentModel");
                }

                if (!string.IsNullOrWhiteSpace(enumValue.ImageName))
                {
                    namespaces.Add("DevExpress.Persistent.Base");
                }
            }

            return namespaces
                .Where(n => !string.IsNullOrWhiteSpace(n))
                .Where(n => n != Enumeration.GetNamespace())
                .Distinct()
                .OrderBy(n => n);
        }
    }

    private static Dictionary<string, string> GetEnumValueAttributes(EnumValue enumValue)
    {
        var attributes = new Dictionary<string, string>();

        if (!string.IsNullOrWhiteSpace(enumValue.Caption))
        {
            attributes.Add("XafDisplayName", $"XafDisplayName(\"{enumValue.Caption}\")");
        }

        if (!string.IsNullOrWhiteSpace(enumValue.Description))
        {
            attributes.Add("Description", $"Description(\"{enumValue.Description.ToSingleLine()}\")");
        }

        if (!string.IsNullOrWhiteSpace(enumValue.ImageName))
        {
            attributes.Add("ImageName", $"ImageName(\"{enumValue.ImageName}\")");
        }

        return attributes;
    }

    public string GenerateCode()
    {
        var code = new StringBuilder();

        var namespaces = Namespaces;
        foreach (var @namespace in namespaces)
        {
            code.AppendLine(RenderTemplate("UsingNamespace", new { Namespace = @namespace }));
        }

        if (namespaces.Any())
        {
            code.AppendLine();
        }

        var enumNamespace = Enumeration.GetNamespace();
        if (!string.IsNullOrWhiteSpace(enumNamespace))
        {
            code.AppendLine(RenderTemplate("Namespace", new { Namespace = enumNamespace }));
            code.AppendLine();
        }

        code.AppendLine(RenderTemplate("TypeSummary", new
        {
            Summary = !string.IsNullOrWhiteSpace(Enumeration.Caption) ? Enumeration.Caption : Enumeration.Name,
            DescriptionLines = Enumeration.Description.ToLines()
        }));

        if (!string.IsNullOrWhiteSpace(Enumeration.Caption) || !string.IsNullOrWhiteSpace(Enumeration.Description))
        {
            var description = Enumeration.Description.ToSingleLine();
            if (string.IsNullOrWhiteSpace(description))
            {
                description = Enumeration.Caption;
            }
            code.AppendLine(RenderTemplate("TypeAttribute", new { TypeAttribute = $"Description(\"{description}\")" }));
        }

        code.AppendLine(RenderTemplate("EnumStatement", new { EnumerationName = Enumeration.Name }));
        code.AppendLine("{");

        for (var i = 0; i < Enumeration.Values.Count; i++)
        {
            var enumValue = Enumeration.Values.ElementAt(i);

            code.AppendLine(RenderTemplate("MemberSummary", new
            {
                Summary = !string.IsNullOrWhiteSpace(enumValue.Caption) ? enumValue.Caption : enumValue.Name,
                DescriptionLines = enumValue.Description.ToLines()
            }));

            var enumValueAttributes = GetEnumValueAttributes(enumValue);
            foreach (var attribute in enumValueAttributes)
            {
                code.AppendLine(RenderTemplate("MemberAttribute", new { MemberAttribute = attribute.Value }));
            }

            code.AppendLine(RenderTemplate("EnumValue", new
            {
                enumValue.Name,
                Value = enumValue.Value.HasValue ? enumValue.Value.ToString() : string.Empty
            }));

            if (Enumeration.Values.Count > 1 && i < Enumeration.Values.Count - 1)
            {
                code.AppendLine();
            }
        }

        code.AppendLine("}");

        return code.ToString();
    }
}
